class DbLinkList {
    constructor({elem, prevPtr = null, nextPtr = null, isHead = false}) {
        this.DbLinkList_elem = elem
        this.DbLinkList_prev = prevPtr
        this.DbLinkList_next = nextPtr
        this.DbLinkList_isHead = isHead
    }

    getListHead() {
        return (function f(dbLink) {
            if (dbLink.DbLinkList_isHead) {
                return dbLink
            }
            return f(dbLink.getPrev())
        }(this));
    }

    ifHead() {
        return this.DbLinkList_isHead
    }

    getElem() {
        return this.DbLinkList_elem
    }

    getPrev() {
        return this.DbLinkList_prev
    }

    setPrev(elemPtr) {
        this.DbLinkList_prev = elemPtr
        return this.DbLinkList_prev
    }

    getNext() {
        return this.DbLinkList_next
    }

    setNext(elemPtr) {
        this.DbLinkList_next = elemPtr
        return this.DbLinkList_next
    }

    getElemByIndex(index) {
        if (index === 0) return this
        let elem = null
        let _elem = this
        if (index > 0) {
            for (; index > 0; index--) {
                _elem = _elem.getNext()
                if (!_elem) {
                    elem = null
                    break
                }
                elem = _elem
            }
        } else if (index < 0) {
            for (; index < 0; index++) {
                _elem = _elem.getPrev()
                if (!_elem) {
                    elem = null
                    break
                }
                elem = _elem
            }
        }
        return elem
    }

    del() {
        this.getPrev().setNext(this.getNext())
        this.DbLinkList_prev = null
        this.DbLinkList_next = null
        return this.getElem()
    }

    add(dbLink) {
        dbLink.setPrev(this)
        this.setNext(dbLink)
        return dbLink
    }

    len() {
        let length = 1;
        (function p(elem) {
            if (!!elem.getPrev()) {
                length++
                p(elem.getPrev())
            }
        })(this);
        (function p(elem) {
            if (!!elem.getNext()) {
                length++
                p(elem.getNext())
            }
        })(this);
        return length
    }

    remainLen() {
        let length = 1;
        (function p(elem) {
            if (!!elem.getNext()) {
                length++
                p(elem.getNext())
            }
        })(this);
        return length
    }
}